package debtbundler.domain.entity.impl;


import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import debtbundler.domain.entity.BalanceSheet;
import debtbundler.domain.entity.Debt;
import debtbundler.domain.entity.Person;
import debtbundler.domain.entity.SharedCost;

public class EntityUpdateNotifierTest {
	
	EntityListener mockListener;
	EntityUpdateNotifier notifier;
	
	@BeforeClass 
	public static void enableLogging() {
		debtbundler.logging.ConfigurationReader.setDefaultConf();
	}

	@Before
	public void setUp() throws Exception {
		mockListener = mock(EntityListener.class);
		notifier = EntityUpdateNotifier.getTheInstance();
		notifier.addEntityListener(mockListener);
	}

	@After
	public void tearDown() throws Exception {
	}
	
	@Test
	public void testEntityUpdateNotifying() {
		PersonImpl person = (PersonImpl) EntityManager.createPerson();
		person.setName("New person");
		verify(mockListener).modelStateChanged(person);
		
		SharedCostImpl cost = (SharedCostImpl) EntityManager.createSharedCost();
		cost.setName("New cost");
		verify(mockListener).modelStateChanged(cost);
		
		PaymentImpl payment = (PaymentImpl) EntityManager.createPayment(person, cost);
		payment.setValue(100);
		verify(mockListener).modelStateChanged(payment);
	}
	
	@Test 
	public void testNotifyingWhenTransactionsAdded() {
		PersonImpl person = (PersonImpl) EntityManager.createPerson();
		SharedCostImpl cost = (SharedCostImpl) EntityManager.createSharedCost();
		PaymentImpl payment = (PaymentImpl) EntityManager.createPayment(person, cost);
		
		verify(mockListener).modelStateChanged(person);
		verify(mockListener).modelStateChanged(cost);
		
		ShareImpl share = (ShareImpl) EntityManager.createShare(person, cost);
		verify(mockListener, times(2)).modelStateChanged(person);
		verify(mockListener, times(2)).modelStateChanged(cost);
		
		PersonImpl creditor = (PersonImpl) EntityManager.createPerson();
		Debt debt = EntityManager.createDebt(person, creditor);
		verify(mockListener, times(3)).modelStateChanged(person);
		verify(mockListener).modelStateChanged(creditor);
	}
	
	@Test
	public void testNotifyingAboutBalanceSheet() {
		BalanceSheet sheet = EntityManager.createBalanceSheet();
		Person person = EntityManager.createPerson();
		SharedCost cost = EntityManager.createSharedCost();
		
		sheet.addMoneyPool(person);
		sheet.addMoneyPool(cost);
		verify(mockListener, times(2)).modelStateChanged(sheet);
	}

	@Test
	public void cannotAddNotiferToListenToItself() {
		boolean added = notifier.addEntityListener(notifier);
		assertFalse(added);
	}
	
}
